package com.hermes.comics.data;

import android.content.Context;

import android.text.TextUtils;
import android.text.format.DateFormat;

import com.hermes.comics.R;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.HashMap;
import java.util.TreeMap;
import java.util.TreeSet;

public abstract class SerieGroup {

  public static class Item {

    private final String key;
    private final String display;
    private final Set<Serie> series;

    Item(String display) {
      this(display, display);
    }

    Item(String key, String display) {
      this.key = key;
      this.display = display;
      this.series = new TreeSet<Serie>();
    }

    public void addSerie(Serie serie) {
      series.add(serie);
    }

    public List<Serie> series() {
      return new ArrayList<Serie>(series);
    }

    public String key() {
      return key;
    }

    public String display() {
      return display;
    }

    @Override
    public String toString() {
      return key;
    }
  }

  private final int resId;
  private final String key;
  private List<Item> items;
  private int position;

  private SerieGroup(int resId, String key) {
    this.resId = resId;
    this.key = key;
    this.items = null;
    this.position = 0;
  }

  public void setPosition(int pos) {
    this.position = pos;
  }

  public Item getCurrentItem(Context context) {
    build(context);
    return items.get(position);
  }

  public List<Map<String, String>> getGroups(Context context) {
    build(context);
    List<Map<String, String>> result = new ArrayList<Map<String, String>>();
    for (Item item : items) {
      Map<String, String> map = new HashMap<String, String>();
      map.put("TITLE", item.display());
      map.put("SUBTITLE", item.series.size() + " series");
      result.add(map);
    }
    return result;
  }

  public List<String> getLabels(Context context) {
    build(context);
    List<String> result = new ArrayList<String>();
    for (Item item : items) {
      result.add(item.display());
    }
    return result;
  }

  public List<Serie> getCurrentSeries(Context context) {
    build(context);
    return items.get(position).series();
  }

  private void build(Context context) {
    Map<String, Item> map = new TreeMap<String, Item>();
    for (Serie serie : Catalog.getInstance().getAllSeries()) {
      Item[] items = apply(context, serie);
      for (Item item : items) {
        Item storedItem = map.get(item.key());
        if (storedItem == null) {
          storedItem = item;
          map.put(item.key(), storedItem);
        }
        storedItem.addSerie(serie);
      }
    }
    items = new ArrayList<Item>(map.values());
    if (isReverse()) {
      Collections.reverse(items);
    }
  }

  public String title(Context context) {
    return context.getString(resId);
  }

  public String key() {
    return key;
  }

  boolean isReverse() {
    return false;
  }

  public Item[] apply(String value) {
    List<Item> result = new ArrayList<Item>();
    if (TextUtils.isEmpty(value)) {
      result.add(new Item(" Unknown"));
    } else {
      for (String format : value.split(Constants.DELIMITER_VALUE)) {
        result.add(new Item(format));
      }
    }
    return result.toArray(new Item[result.size()]);
  }

  public abstract Item[] apply(Context context, Serie serie);

  // ------------------ DEFINITIONS ---------------------------------

  public static final SerieGroup READ = new SerieGroup(R.string.tag_read, "READ") {
    @Override
    public Item[] apply(Context context, Serie serie) {
      List<Item> result = new ArrayList<Item>();
      for (Issue issue : serie.issues()) {
        String read = IssueTag.READ.value(issue);
        if (TextUtils.isEmpty(read) ||"N".equals(read)) continue;

        Calendar calendar = issue.getReadDate();
        String key = DateFormat.format("yyyy/MM", calendar).toString();
        String display = DateFormat.format("yyyy/MMMM", calendar).toString();

        result.add(new Item(key, display));
      }
      return result.toArray(new Item[result.size()]);
    }

    @Override
    boolean isReverse() {
      return true;
    }
  };

  public static final SerieGroup FEATURES = new SerieGroup(R.string.tag_features, "FEATURES") {
    @Override
    public Item[] apply(Context context, Serie serie) {
      List<Item> result = new ArrayList<Item>();

      result.add(new Item("All series"));

      int count = 0;
      for (Issue issue : serie.issues()) {
        if (TextUtils.isEmpty(IssueTag.IMG.value(issue))) {
          count++;
        }
      }
      if (count > 0) {
        result.add(new Item(context.getString(R.string.group_without_picture)));
      }

      if (!TextUtils.isEmpty(serie.getTagValue(SerieTag.NOTE))) {
        result.add(new Item(context.getString(R.string.group_with_note)));
      }

      if ("Y".equals(serie.getTagValue(SerieTag.UNREVIEWED))) { 
        result.add(new Item(context.getString(R.string.group_unreview)));
      } else if (!serie.missing().isEmpty()) {
        result.add(new Item(context.getString(R.string.group_incomplete)));
      }

      if (serie.read().size() != serie.issues().size()) {
        result.add(new Item(context.getString(R.string.group_unread)));
      }

      return result.toArray(new Item[result.size()]);
    }
  };

  public static final SerieGroup LANGUAGE = new SerieGroup(R.string.tag_language, "LANGUAGE") {
    @Override
    public Item[] apply(Context context, Serie serie) {
      String language = SerieTag.LANGUAGE.value(serie);

      int lang_id = context.getResources().getIdentifier(
          "language_" + language, "string", context.getPackageName());

      return new Item[] { new Item(context.getResources().getString(lang_id)) };
    }
  };

//  public static final SerieGroup ALPHA = new SerieGroup(R.string.tag_alpha, "ALPHA") {
//    @Override
//    public Item[] apply(Context context, Serie serie) {
//      String letter = serie.getTagValue(SerieTag.TITLE).toUpperCase().substring(0, 1);
//      return new Item[] { new Item(letter.matches("[0-9]") ? "0-9" : letter) };
///    }
//  };

  public static final SerieGroup FORMAT = new SerieGroup(R.string.tag_format, "FORMAT") {
    @Override
    public Item[] apply(Context context, Serie serie) {
      return apply(SerieTag.FORMAT.value(serie));
    }
  };

  public static final SerieGroup GENRE = new SerieGroup(R.string.tag_genre, "GENRE") {
    @Override
    public Item[] apply(Context context, Serie serie) {
      return apply(SerieTag.GENRE.value(serie));
    }
  };

  public static final SerieGroup PUBLISHER = new SerieGroup(R.string.tag_publisher, "PUBLISHER") {
    @Override
    public Item[] apply(Context context, Serie serie) {
      return apply(SerieTag.PUBLISHER.value(serie));
    }
  };

  public static final SerieGroup AUTHOR = new SerieGroup(R.string.tag_author, "AUTHOR") {
    @Override
    public Item[] apply(Context context, Serie serie) {
      return apply(SerieTag.AUTHOR.value(serie));
    }
  };

  public static final SerieGroup CATEGORY = new SerieGroup(R.string.tag_category, "CATEGORY") {
    @Override
    public Item[] apply(Context context, Serie serie) {
      return apply(SerieTag.CATEGORY.value(serie));
    }
  };

  public static final SerieGroup[] GROUPS = {
      SerieGroup.FEATURES, SerieGroup.AUTHOR, SerieGroup.CATEGORY, SerieGroup.FORMAT, 
      SerieGroup.READ, SerieGroup.PUBLISHER, SerieGroup.LANGUAGE, SerieGroup.GENRE,
  };
}
